package protocol

import (
	"fmt"
	"github.com/wanchain/go-mpc/common"
	"github.com/wanchain/go-mpc/common/hexutil"
	"time"
)

type SendData struct {
	PKBytes hexutil.Bytes `json:"pk"`
	Data    hexutil.Bytes `json:"data"`
	Curve   hexutil.Bytes `json:"curve"`
	Extern  string        `json:extern`
}

// add by Jacob for uniMpc begin
type SignInput struct {
	PKBytes  hexutil.Bytes   `json:"pk"`
	Curve    hexutil.Bytes   `json:"curve"`
	Alg      hexutil.Bytes   `json:"alg"`
	HashData []hexutil.Bytes `json:"hashData"`
	RawData  []hexutil.Bytes `json:"rawData"`
	Extern   string          `json:extern`
}

type SignInputWithStamp struct {
	SignInput
	RcvTimeStamp time.Time `json:rcvTime`
}

func (d *SignInput) String() string {
	var hashHexStringes string
	for i := 0; i < len(d.HashData); i++ {
		hashHexStringes += " " + hexutil.Encode(d.HashData[i])
	}

	var rawDataStringes string
	for i := 0; i < len(d.RawData); i++ {
		rawDataStringes += " " + string(d.RawData[i])
	}

	return fmt.Sprintf(
		"pk: %s Curve:%s Alg:%s Extern:%s HashData:%s",
		hexutil.Encode([]byte(d.PKBytes[:])),
		hexutil.Encode(d.Curve[:]),
		hexutil.Encode(d.Alg[:]),
		d.Extern,
		hashHexStringes)
}

type SignOutput struct {
	ResultType uint8
	GrpId      hexutil.Bytes `json:"GrpId"`
	CurveType  uint8

	Sig []hexutil.Bytes `json:"Sig"`

	// uint256, one bit, one sm index
	IncntData     hexutil.Bytes   `json:"IncntData"`
	FinishCollect hexutil.Bytes   `json:"FinishCollect"`
	RNW           hexutil.Bytes   `json:"RNW"`
	SNW           hexutil.Bytes   `json:"SNW"`
	RSlsh         []RSlshPrf      `json:"RSlsh"`
	SSlsh         []SSlshPrf      `json:"SSlsh"`
	HashData      []hexutil.Bytes `json:"HashData"`
}

func (d *SignOutput) String() string {
	return fmt.Sprintf(
		"ResultType: %d IncntData: %s",
		d.ResultType,
		hexutil.Encode(d.IncntData[:]))
}

// add by Jacob for uniMpc end

func (d *SendData) String() string {
	return fmt.Sprintf(
		"pk: %s From:%s Curve:%s Extern:%s", hexutil.Encode([]byte(d.PKBytes[:])),
		hexutil.Encode([]byte(d.Data[:])),
		hexutil.Encode(d.Curve[:]),
		d.Extern)
}

type SignedResult struct {
	R hexutil.Bytes `json:"R"`
	S hexutil.Bytes `json:"S"`

	ResultType uint8
	CurveType  uint8
	GrpId      hexutil.Bytes `json:"GrpId"`

	// uint256, one bit, one sm index
	IncntData hexutil.Bytes `json:"IncntData"`
	RNW       hexutil.Bytes `json:"RNW"`
	SNW       hexutil.Bytes `json:"SNW"`
	RSlsh     []RSlshPrf    `json:"RSlsh"`
	SSlsh     []SSlshPrf    `json:"SSlsh"`
}

type SignedSuccResult struct {
	SignedResult
	SignedBtc []hexutil.Bytes `json:"SignedBtc"`
}
type SignedDataResult struct {
	SignedResult
	SignedData hexutil.Bytes `json:"SignedData"`
}

///////////////////////// add for Btc begin
type SendTxArgs struct {
	From      common.Address  `json:"from"`
	To        *common.Address `json:"to"`
	Gas       *hexutil.Big    `json:"gas"`
	GasPrice  *hexutil.Big    `json:"gasPrice"`
	Value     *hexutil.Big    `json:"value"`
	Data      hexutil.Bytes   `json:"data"`
	Nonce     *hexutil.Uint64 `json:"nonce"`
	ChainType string          `json:"chainType"` // 'WAN' or 'ETH'
	ChainID   *hexutil.Big    `json:"chainID"`
	SignType  string          `json:"signType"` //input 'hash' for hash sign (r,s,v), else for full sign(rawTransaction)
}

func (tx *SendTxArgs) String() string {
	return fmt.Sprintf(
		"From:%s, To:%s, Gas:%s, GasPrice:%s, Value:%s, Data:%s, Nonce:%d, ChainType:%s, ChainID:%s, SignType:%s",
		tx.From.String(),
		tx.To.String(),
		tx.Gas.String(),
		tx.GasPrice.String(),
		tx.Value.String(),
		common.ToHex(tx.Data),
		*tx.Nonce,
		tx.ChainType,
		tx.ChainID.String(),
		tx.SignType)
}

///////////////////////// add for Btc end

type SendEcData struct {
	PKBytes      hexutil.Bytes `json:"pKBytes"`
	TxHash       hexutil.Bytes `json:txHash`      // the raw tx data 's hash // 是否保留.
	TxData       string        `json:txData`      //  raw tx of the chain
	ChainType    string        `json:"chainType"` // 'WAN' or 'ETH',  xrp
	TxId         hexutil.Bytes `json:txId`        // TODO, how to specify the unique ID, for example, hashX/txhashID.
	RcvTimeStamp time.Time
}

func (tx *SendEcData) String() string {
	return fmt.Sprintf("sdata: %s", tx.TxData, tx.TxHash.String(), tx.PKBytes.String(), tx.ChainType)
}
